<?php

declare(strict_types=1);

namespace App\Job;

use _PHPStan_adbc35a1c\Nette\Neon\Exception;
use App\Model\Applet;
use App\Model\AppletPlayletRel;
use App\Model\Playlet;
use App\Model\PlayletActor;
use App\Model\PlayletEpisodes;
use GuzzleHttp\Client;
use Hyperf\AsyncQueue\Job;
use Psr\Log\LoggerInterface;
use Hyperf\Utils\ApplicationContext;
use Hyperf\Logger\LoggerFactory;
use function PHPUnit\Framework\exactly;

class WxDramaJob extends Job
{

    public $playet_id;

    public $applet_id;
    protected LoggerInterface $logger;


    //获取token
    public static $getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token";

    //临时素材接口，上传对应的剧目封面图
    public static $uploadImageUrl = "https://api.weixin.qq.com/cgi-bin/media/upload";

    //剧目提审
    public static $auditdramaUrl = "https://api.weixin.qq.com/wxa/sec/vod/auditdrama";
    public function __construct(int $playet_id,int $applet_id)
    {
        $container = ApplicationContext::getContainer();
        $this->logger = $container->get(LoggerFactory::class)->get('log', 'wxvod');
        $this->playet_id = $playet_id;
        $this->applet_id = $applet_id;
    }

    public function handle()
    {
        try {
            $this->logger->info('开始上传提审剧目');
            $this->logger->info('查询短剧是否存在',[$this->playet_id]);
            //获取短剧ID
            $playletData = Playlet::query()->where(['id' => $this->playet_id])->first();

            if(!empty($playletData)){

                $this->logger->info('查询小程序是否存在',[$this->applet_id]);
                $appletData = Applet::query()->where(['id' => $this->applet_id])->first();
                if(!empty($appletData)) {
                    $applet_name = $appletData->name;
                    $playlet_name = $playletData->name;

                    //获取token
                    $accessToken = $this->getWxAccessToken($appletData->id,$appletData->app_id,$appletData->app_secret);
                    if(!empty($accessToken)){

                        $episodes_count = PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id])->count();
                        //统计短剧剧集总数
                        $media_id_list = PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id,'is_upload' => 3])
                                                ->where('media_id','!=',0)
                                                ->orderBy('playlet_number','asc')
                                                ->pluck('media_id')->toArray();
                        $media_count = count($media_id_list);

                        if($episodes_count == $media_count && $media_count != 0){

                            $media_id = 0;
                            $drama_id = 0;
                            $producer = $playletData->producer;
                            $introduction = $playletData->introduction;
                            $authorized_material_id = '';
                            $registration_number = '';
                            $replace_media_list = array();

                            $this->logger->info('小程序：'.$applet_name.' 短剧：'.$playlet_name.'调用临时素材接口，上传封面图');
                            $media_id = $this->dramaImageUpload($accessToken,$playletData->cover);
                            $authorized_material_id = $this->dramaImageUpload($accessToken,$playletData->registration_number_url);
                            $registration_number = $playletData->registration_number;
                            //重新提审
                            if(!empty($playletData->drama_id)){

                                $drama_id = $playletData->drama_id;

                                //需要替换的集数
                                $replaceMediaList = PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id,'is_upload' => 3])
                                    ->select(['id','media_id','old_media_id'])
                                    ->where('media_id','!=',0)
                                    ->where('old_media_id','!=',0)
                                    ->get()->toArray();


                                if(!empty($replaceMediaList)){

                                    foreach ($replaceMediaList as $item){
                                        $replace_media_list[] = [
                                            'old' => $item['old_media_id'],
                                            'new' => $item['media_id']
                                        ];
                                    }
                                }
                            }
                            //2024-03-13 //获取这部短剧的演员
                            $this->logger->info('小程序：' . $applet_name . ' 短剧：' . $playlet_name . '获取这部剧的角色');
                            $playletActorData = PlayletActor::query()->where(['playlet_id' => $this->playet_id])
                                ->leftJoin('actor','playlet_actor.actor_id','=','actor.id')
                                ->select(['name','role_name','cover','profile'])->get();
                            if(!empty($playletActorData)){
                                $actor = [];
                                foreach ($playletActorData as $playletActorDatum){
                                    //上传演员图片
                                    $photo_material_id = '';
                                    $photo_material_id = $this->dramaImageUpload($accessToken,$playletActorDatum->cover);
                                    $actor[] = [
                                        'name' => $playletActorDatum->name,
                                        'photo_material_id' => $photo_material_id,
                                        'role' => $playletActorDatum->role_name,
                                        'profile' => $playletActorDatum->profile,
                                    ];
                                }
                                $actor_list['actor'] = $actor;

                                $this->logger->info('小程序：' . $applet_name . ' 短剧：' . $playlet_name . '开始上传剧目');
                                $returnDramaData = $this->auditDramaUpload($accessToken,
                                    $playlet_name, //剧目名称
                                    $introduction, //剧目名称
                                    $producer,      //剧目制作方
                                    $media_id,      //封面图片临时media_id
                                    $authorized_material_id, //剧目播放授权材料material_id
                                    $drama_id, //剧目ID
                                    $registration_number, //剧目备案号
                                    $media_count,
                                    $media_id_list,
                                    $replace_media_list,
                                    $actor_list //演员列表
                                );

                                if($returnDramaData['errcode'] == 0){

                                    $playletData->drama_id = $returnDramaData['drama_id'];
                                    $playletData->drama_status = 1;
                                    $playletData->save();

                                    if(!empty($media_id_list)){
                                        PlayletEpisodes::query()->where(['playlet_id' => $this->playet_id,'is_upload' => 3])
                                            ->where('media_id','!=',0)
                                            ->where('media_status','=',0)
                                            ->update(['media_status' => 1]);
                                    }
                                    if(!empty($replace_media_list)){
                                        foreach ($replaceMediaList as $item){
                                            $item->old_media_id = 0;
                                            $item->save();
                                        }
                                    }
                                }else{

                                    $playletData->drama_msg = $returnDramaData['errcode'];
                                    $playletData->save();
                                }

                            }else{
                                $this->logger->error('小程序：'.$applet_name.' 短剧：'.$playlet_name.'没有绑定角色');
                            }
                        }else{
                            $this->logger->error('小程序：'.$applet_name.' 短剧：'.$playlet_name.'拥有的剧集和上传成功的剧集不一致');
                        }
                    }else{
                        $this->logger->error('小程序:'.$applet_name.' 短剧:'.$playlet_name.' 没有对应的token');
                    }

                }else{
                    $this->logger->error('小程序不存在',[$this->applet_id]);
                }
            }else{
                $this->logger->error('短剧不存在',[$this->playet_id]);
            }
        }catch (\Exception $e){
            $playletData->drama_status = 5;
            $playletData->drama_msg = $e->getMessage();
            $playletData->save();
            $this->logger->error('请求微信提交审核剧目接口|错误：' . $e->getLine() . '|' . $e->getMessage());
        }
    }


    public function dramaImageUpload($accessToken,$cover_url){

        $coverArr = explode('/',$cover_url);
        $description = array(
            'title' => $coverArr[count($coverArr)-1],
            'introduction' =>   $coverArr[count($coverArr)-1],
        );

        $localPath = BASE_PATH.'/runtime/image.jpg';
        $imgContent = file_get_contents($cover_url);
        file_put_contents($localPath, $imgContent);

        $params = [
            [
                'name'     => 'media',
                'contents' => fopen($localPath, 'r')
            ],
            [
                'name' => 'description',
                'contents' => urldecode(json_encode($description))
            ]
        ];

        $uploadUrl = self::$uploadImageUrl.'?access_token='.$accessToken.'&type=image';
        $this->logger->info('请求数据：'.PHP_EOL.var_export(['result' => $description], true));
        $this->logger->info('请求Url：'.$uploadUrl);
        //开始上传
        $uploadResult  = $this->request($params, $uploadUrl,'POST',true);
        if(empty($uploadResult['errcode'])){
            $this->logger->info('上传图片成功 返回数据：'.PHP_EOL.var_export(['result' => $uploadResult], true));
            $media_id = $uploadResult['media_id'];
            return $media_id;
        }else{
            $this->logger->error('上传图片失败 返回数据：'.PHP_EOL.var_export(['result' => $uploadResult], true));
        }
        return false;
    }


    public function getWxAccessToken($applet_id,$app_id,$app_secret){

        $container = ApplicationContext::getContainer();

        $redis = $container->get(\Hyperf\Redis\RedisFactory::class)->get('wx');

        $key = 'wx_access_token';
        $key .= $applet_id;
        $accessToken = $redis->get($key);
//        if(empty($accessToken)){
            $params         = [
                'grant_type' => 'client_credential',
                'appid'    => $app_id,
                'secret'   => $app_secret
            ];
            //获取token
            $accessTokenInfo     = $this->request($params, self::$getTokenUrl,'GET');

            if (!empty($accessTokenInfo['access_token'])){
                $accessToken = $accessTokenInfo['access_token'];
                $redis->setex($key,7100,$accessToken);
            }else{
                $accessToken = "";
            }
//        }
        return $accessToken;
    }

    public function auditDramaUpload($accessToken, $playlet_name,$description, $producer, $media_id=0,$authorized_material_id=0,$drama_id=0,$registration_number=0,$media_count=0,$media_id_list = array(),$replace_media_list = array(),$actor_list = array()){
        //首次提审
        $params = [
            'name' => $playlet_name,
            'description' => $description,
        ];
        if(!empty($media_id)){
            $params['cover_material_id'] = $media_id;
        }
        if(!empty($drama_id)){
            $params['drama_id'] = $drama_id;
        }else{
            //2024-3-13 新增演员列表
            $params['actor_list'] = $actor_list;
            $params['media_count'] = $media_count;
            $params['media_id_list'] = $media_id_list;
        }
        $params['producer'] = $producer;
        if(!empty($authorized_material_id)){
            $params['registration_number'] = $registration_number;
            $params['authorized_material_id'] = $authorized_material_id;
        }

        if(!empty($replace_media_list)){
            $params['replace_media_list'] = $replace_media_list;
        }

        $dramaUrl = self::$auditdramaUrl.'?access_token='.$accessToken;
        $this->logger->info('请求媒资数据：'.PHP_EOL.var_export(['result' => $params], true));
        $this->logger->info('请求媒资Url：'.$dramaUrl);
        //开始上传
        $postResult  = $this->request($params, $dramaUrl,'POST');

        if($postResult['errcode'] == 0){
            $this->logger->info('调用媒资接口成功 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
            return $postResult;
        }else{
            $this->logger->error('调用媒资接口失败 返回数据：'.PHP_EOL.var_export(['result' => $postResult], true));
        }
        return false;
    }


    /**
     * 传入数组进行HTTP POST请求
     */
    function request(array $params, string $url,string $method,$is_multipart = false)
    {
        $client   = new Client([
            'timeout' => 3
        ]);
        if ($is_multipart) {
            $headers       =['Content-Type' => 'multipart/form-data'];
        }else{
            $headers       =['Content-Type' => 'application/json;charset=utf-8', 'Accept' => 'application/json','Accept-Charset' => 'utf-8'];
        }

        $requestParams = [
            'headers' => $headers,
        ];
        if ($method == 'GET') {
            $requestParams['query'] = $params;
        } else {
            if ($is_multipart) {
                $requestParams['multipart'] = $params;
            } else  {
                $requestParams['body'] = json_encode($params,JSON_UNESCAPED_UNICODE);
            }
        }

        $response = $client->request($method,$url, $requestParams);

        if ($response->getStatusCode() !== 200) {
            return '';
        }
        $result   = $response->getBody()->getContents();
        $resultArr = json_decode($result,true);
        return $resultArr;

    }
}